package com.mango.banner.widget;

import android.content.Context;
import android.content.res.TypedArray;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;

import com.mango.banner.R;
import com.mango.banner.WeakHandler;
import com.mango.banner.widget.ImageLoader.ImageLoaderInterface;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

/**
 * @author Angry-Banana
 * @date 2018-10-22
 */
public class Banner extends FrameLayout implements ViewPager.OnPageChangeListener {

    private static final String TAG = "com.mango.banner";

    private Context mContext;
    private int mCurrentItem;
    // 轮播图数量
    private int mCount;
    // 自动轮播间隔
    private int mDelayTime;
    // 滚动时间
    private int mScrollTime;
    // 指示器的大小
    private int mIndicatorSize;
    // 图片缩放类型
    private int mScaleType;
    private int mLastPosition;
    // 指示器的间距
    private int mIndicatorMargin;
    private int mIndicatorSelectedRes;
    private int mIndicatorUnSelectedRes;
    private BannerAdapter mAdapter;
    private ViewPager mViewPager;
    private boolean mIsAutoPlay;
    private ImageLoaderInterface mImageLoader;
    private LinearLayout mCircleIndicator;
    private BannerScroller mScroller;
    private BannerListener mBannerListener;
    private List mImageUrls = new ArrayList<>();
    private List<ImageView> mIndicatorViews = new ArrayList<>();
    private List<View> mImageViews = new ArrayList<>();
    private WeakHandler mHandler = new WeakHandler();

    public Banner(Context context) {
        this(context, null);
    }

    public Banner(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public Banner(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        mContext = context;
        handleTypedArray(context, attrs);
        View view = LayoutInflater.from(context).inflate(R.layout.widget_banner, this, true);
        initView(view);
        initViewPagerScroll();
    }

    private void handleTypedArray(Context context, AttributeSet attrs) {
        if (attrs == null) {
            return;
        }
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.Banner);
        mDelayTime = typedArray.getInt(R.styleable.Banner_delay_time, 3000);
        mScrollTime = typedArray.getInt(R.styleable.Banner_scroll_time, 800);
        mIndicatorSize = typedArray.getInt(R.styleable.Banner_indicator_size, 25);
        mIndicatorMargin = typedArray.getInt(R.styleable.Banner_indicator_margin, mIndicatorSize / 2);
        mIndicatorSelectedRes = typedArray.getInt(R.styleable.Banner_indicator_select_res, R.drawable.gray_radius);
        mIndicatorUnSelectedRes = typedArray.getInt(R.styleable.Banner_indicator_un_select_res,
                R.drawable.white_radius);
        mIsAutoPlay = typedArray.getBoolean(R.styleable.Banner_is_auto_play, true);
        mScaleType = typedArray.getInt(R.styleable.Banner_image_scale_type, 1);
        typedArray.recycle();
    }


    private void initView(View view) {
        mViewPager = view.findViewById(R.id.view_pager);
        mCircleIndicator = view.findViewById(R.id.circle_indicator);
    }

    private void initViewPager() {
        mCurrentItem = 0;
        mLastPosition = 0;
        if (mAdapter == null) {
            mAdapter = new BannerAdapter(mImageViews, mBannerListener);
        }
        mViewPager.setAdapter(mAdapter);
        mViewPager.setCurrentItem(mCurrentItem);
        mViewPager.setFocusable(true);
        mViewPager.addOnPageChangeListener(this);
    }

    private void initViewPagerScroll() {
        try {
            Field field = ViewPager.class.getDeclaredField("mScroller");
            field.setAccessible(true);
            mScroller = new BannerScroller(mViewPager.getContext());
            mScroller.setDuration(mScrollTime);
            field.set(mViewPager, mScroller);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void setImageViews() {
        if (mImageLoader == null) {
            Log.e(TAG, "imageLoader can not be null!");
            return;
        }
        mCount = mImageUrls.size();
        for (int i = 0; i < mCount; i++) {
            View imageView = mImageLoader.createImageView(mContext);
            mImageLoader.displayImage(mContext, mImageUrls.get(i), imageView);
            setScaleType(imageView);
            mImageViews.add(imageView);
        }
    }

    private void setIndicator() {
        for (int i = 0; i < mCount; i++) {
            ImageView imageView = new ImageView(mContext);
            if (i == mCurrentItem) {
                imageView.setImageResource(mIndicatorSelectedRes);
            } else {
                imageView.setImageResource(mIndicatorUnSelectedRes);
            }
            LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
                    mIndicatorSize, mIndicatorSize);
            params.leftMargin = mIndicatorMargin / 2;
            params.rightMargin = mIndicatorMargin / 2;
            mIndicatorViews.add(imageView);
            mCircleIndicator.addView(imageView, params);
        }
    }

    private void setScaleType(View imageView) {
        if (imageView instanceof ImageView) {
            ImageView view = ((ImageView) imageView);
            switch (mScaleType) {
                case 0:
                    view.setScaleType(ImageView.ScaleType.CENTER);
                    break;
                case 1:
                    view.setScaleType(ImageView.ScaleType.CENTER_CROP);
                    break;
                case 2:
                    view.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
                    break;
                case 3:
                    view.setScaleType(ImageView.ScaleType.FIT_CENTER);
                    break;
                case 4:
                    view.setScaleType(ImageView.ScaleType.FIT_END);
                    break;
                case 5:
                    view.setScaleType(ImageView.ScaleType.FIT_START);
                    break;
                case 6:
                    view.setScaleType(ImageView.ScaleType.FIT_XY);
                    break;
                case 7:
                    view.setScaleType(ImageView.ScaleType.MATRIX);
                    break;
            }
        }
    }

    public void starAutoPlay() {
        mHandler.removeCallbacks(task);
        mHandler.postDelayed(task, mDelayTime);
    }

    public void stopAutoPlay() {
        mHandler.removeCallbacks(task);
    }

    private final Runnable task = new Runnable() {
        @Override
        public void run() {
            if (mCount > 1 && mIsAutoPlay) {
                mCurrentItem = (mCurrentItem + 1) % mCount;
                mViewPager.setCurrentItem(mCurrentItem);
                mHandler.postDelayed(task, mDelayTime);
            }
        }
    };

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        if (mIsAutoPlay) {
            int action = ev.getAction();
            if (action == MotionEvent.ACTION_UP
                    || action == MotionEvent.ACTION_CANCEL
                    || action == MotionEvent.ACTION_OUTSIDE) {
                starAutoPlay();
            } else if (action == MotionEvent.ACTION_DOWN) {
                stopAutoPlay();
            }
        }
        return super.dispatchTouchEvent(ev);
    }

    @Override
    public void onPageScrolled(int i, float v, int i1) {

    }

    @Override
    public void onPageSelected(int position) {
        mCurrentItem = position;
        mIndicatorViews.get(position).setImageResource(R.drawable.gray_radius);
        mIndicatorViews.get(mLastPosition).setImageResource(R.drawable.white_radius);
        mLastPosition = position;
    }

    @Override
    public void onPageScrollStateChanged(int state) {
    }

    public void start() {
        setImageViews();
        setIndicator();
        initViewPager();
        if (mIsAutoPlay) {
            starAutoPlay();
        }
    }

    public int getDelayTime() {
        return mDelayTime;
    }

    public void setDelayTime(int delayTime) {
        mDelayTime = delayTime;
    }

    public int getScrollTime() {
        return mScrollTime;
    }

    public void setScrollTime(int scrollTime) {
        mScrollTime = scrollTime;
    }

    public boolean isAutoPlay() {
        return mIsAutoPlay;
    }

    public void setAutoPlay(boolean autoPlay) {
        mIsAutoPlay = autoPlay;
    }

    public int getScaleType() {
        return mScaleType;
    }

    public void setScaleType(int scaleType) {
        mScaleType = scaleType;
    }

    public BannerListener getBannerListener() {
        return mBannerListener;
    }

    public void setBannerListener(BannerListener bannerListener) {
        mBannerListener = bannerListener;
    }

    public List getImageUrls() {
        return mImageUrls;
    }

    public void setImageUrls(List imageUrls) {
        mImageUrls = imageUrls;
    }

    public int getIndicatorSize() {
        return mIndicatorSize;
    }

    public void setIndicatorSize(int indicatorSize) {
        mIndicatorSize = indicatorSize;
    }

    public int getIndicatorMargin() {
        return mIndicatorMargin;
    }

    public void setIndicatorMargin(int indicatorMargin) {
        mIndicatorMargin = indicatorMargin;
    }

    public int getIndicatorSelectedRes() {
        return mIndicatorSelectedRes;
    }

    public void setIndicatorSelectedRes(int indicatorSelectedRes) {
        mIndicatorSelectedRes = indicatorSelectedRes;
    }

    public int getIndicatorUnSelectedRes() {
        return mIndicatorUnSelectedRes;
    }

    public void setIndicatorUnSelectedRes(int indicatorUnSelectedRes) {
        mIndicatorUnSelectedRes = indicatorUnSelectedRes;
    }

    public ImageLoaderInterface getImageLoader() {
        return mImageLoader;
    }

    public void setImageLoader(ImageLoaderInterface imageLoader) {
        mImageLoader = imageLoader;
    }
}
